package org.mybatis.generator.plugins;

import java.util.List;
import java.util.Properties;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;

/**
 * <b><code>LombokPlugin</code></b>
 * <p/>
 * Description: LombokPlugin插件
 * <p/>
 * <b>Creation Time:</b> 2020/06/08.
 */
public class LombokPlugin extends PluginAdapter {

	/**
	 * 是否需要生成Data注解
	 */
	private boolean needsData;

	/**
	 * 是否需要生成Getter注解
	 */
	private boolean needsGetter;

	/**
	 * 是否需要生成Setter注解
	 */
	private boolean needsSetter;

	/**
	 * 是否需要生成ToString注解
	 */
	private boolean needsToString;

	/**
	 * 是否需要生成Builder注解
	 */
	private boolean needsBuilder;

	/**
	 * 是否需要生成Accessors(chain = true)注解
	 */
	private boolean needsAccessors;

	/**
	 * 是否需要生成NoArgsConstructor注解
	 */
	private boolean needsNoArgsConstructor;

	/**
	 * 是否需要生成AllArgsConstructor注解
	 */
	private boolean needsAllArgsConstructor;

	/**
	 * 是否需要生成EqualsAndHashCode注解
	 */
	private boolean needsEqualsAndHashCode;

	/**
	 * 是否需要生成EqualsAndHashCode注解，并且“callSuper = true”
	 */
	private boolean needsEqualsAndHashCodeAndCallSuper;

	public LombokPlugin() {
		super();
		needsData = false;
		needsGetter = false;
		needsSetter = false;
		needsToString = false;
		needsBuilder = false;
		needsAccessors = false;
		needsNoArgsConstructor = false;
		needsAllArgsConstructor = false;
		needsEqualsAndHashCode = false;
		needsEqualsAndHashCodeAndCallSuper = false;
	}

	@Override
	public boolean validate(List<String> warnings) {
		// this plugin is always valid
		return true;
	}

	@Override
	public void setProperties(Properties properties) {
		String lombok = properties.getProperty("lombok");
		if (lombok != null && !"".equals(lombok)) {
			this.needsData = lombok.contains("Data");
			// @Data 优先级高于 @Getter @Setter @RequiredArgsConstructor @ToString
			// @EqualsAndHashCode
			this.needsGetter = !this.needsData && lombok.contains("Getter");
			this.needsSetter = !this.needsData && lombok.contains("Setter");
			this.needsToString = !this.needsData && lombok.contains("ToString");
			this.needsBuilder = lombok.contains("Builder");
			this.needsNoArgsConstructor = lombok.contains("NoArgsConstructor");
			this.needsAllArgsConstructor = lombok.contains("AllArgsConstructor");
			this.needsEqualsAndHashCode = !this.needsData && lombok.contains("EqualsAndHashCode");
			// 配置lombok扩展EqualsAndHashCode注解是否添加“callSuper = true”
			String lombokEqualsAndHashCodeCallSuper = properties.getProperty("lombokEqualsAndHashCodeCallSuper",
					"false");
			this.needsEqualsAndHashCodeAndCallSuper = this.needsEqualsAndHashCode
					&& "TRUE".equalsIgnoreCase(lombokEqualsAndHashCodeCallSuper);
			this.needsAccessors = lombok.contains("Accessors");
		}
	}

	@Override
	public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		// 如果需要Data，引入包，代码增加注解
		if (this.needsData) {
			topLevelClass.addImportedType("lombok.Data");
			topLevelClass.addAnnotation("@Data");
		}
		// 如果需要Getter，引入包，代码增加注解
		if (this.needsGetter) {
			topLevelClass.addImportedType("lombok.Getter");
			topLevelClass.addAnnotation("@Getter");
		}
		// 如果需要Setter，引入包，代码增加注解
		if (this.needsSetter) {
			topLevelClass.addImportedType("lombok.Setter");
			topLevelClass.addAnnotation("@Setter");
		}
		// 如果需要ToString，引入包，代码增加注解
		if (this.needsToString) {
			topLevelClass.addImportedType("lombok.ToString");
			topLevelClass.addAnnotation("@ToString");
		}
		// 如果需要Builder，引入包，代码增加注解
		if (this.needsBuilder) {
			topLevelClass.addImportedType("lombok.Builder");
			topLevelClass.addAnnotation("@Builder");
		}
		// 如果需要NoArgsConstructor，引入包，代码增加注解
		if (this.needsNoArgsConstructor) {
			topLevelClass.addImportedType("lombok.NoArgsConstructor");
			topLevelClass.addAnnotation("@NoArgsConstructor");
		}
		// 如果需要AllArgsConstructor，引入包，代码增加注解
		if (this.needsAllArgsConstructor) {
			topLevelClass.addImportedType("lombok.AllArgsConstructor");
			topLevelClass.addAnnotation("@AllArgsConstructor");
		}
		// 如果需要EqualsAndHashCode，并且“callSuper = true”，引入包，代码增加注解
		if (this.needsEqualsAndHashCodeAndCallSuper) {
			topLevelClass.addImportedType("lombok.EqualsAndHashCode");
			topLevelClass.addAnnotation("@EqualsAndHashCode(callSuper = true)");
		} else {
			// 如果需要EqualsAndHashCode，引入包，代码增加注解
			if (this.needsEqualsAndHashCode) {
				topLevelClass.addImportedType("lombok.EqualsAndHashCode");
				topLevelClass.addAnnotation("@EqualsAndHashCode");
			}
		}
		// 如果需要Accessors，引入包，代码增加注解
		if (this.needsAccessors) {
			topLevelClass.addImportedType("lombok.experimental.Accessors");
			topLevelClass.addAnnotation("@Accessors(chain = true)");
		}
		return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable);
	}

	@Override
	public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass,
			IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return !(needsData || needsGetter);
	}

	@Override
	public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass,
			IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return !(needsData || needsGetter);
	}

}
